#!/usr/bin/env python
#-*- coding:utf-8 -*-

"""
    PySeq0 - a python sequencer
    (c) by Tobias Sauer 2011
    Copyright: GPL v2 only
    http://leichtdio.de
    tobias@leichtdio.de
    
    Google Code:
    http://pyseq0.leichtdio.de
"""

import json, thread
from os.path import join
from glob import glob

import midi
import logging
_log = logging.getLogger("Jukebox")

from sequence import LoopClass, DrumClass
from beater import BeatClock

class Song:
    """
        administrate one song
    """
    def __init__(self, songdic, midihandler):
        self.songdic = songdic #workaround for autosongselect
        self.meta = {
                     "name" : songdic["name"],
                     "author" : songdic["author"],
                     "copyright" : songdic["copyright"],
                     "bpm" : songdic["bpm"],
                    }
        self.loops = []
        self.drums = []
        self.play = False
        self.midi = midihandler
        self.clock = BeatClock(self.meta["bpm"])

        self.allmidinames = []

        for drumdic in songdic["drums"]:
            self.drums.append(DrumClass(drumdic, self.meta["bpm"], self.midi))
            for drum in drumdic["content"]:
                self.allmidinames.append(drum)

        for loopdic in songdic["loops"]:
            self.loops.append(LoopClass(loopdic, self.meta["bpm"], self.midi))
            self.allmidinames.append(loopdic["midiname"])

    def start_clock(self):
        self.play = True
        thread.start_new_thread(self.clock.main_loop, ())

    def stop_clock(self):
        self.play = False
        self.clock.stop()

    def get_allpads (self):
        return self.loops, self.drums

    def checkdrum(self, drumid):
        drum = self.drums[drumid]
        self.clock.add((drum, ()))

    def checkloop(self, loopid):
        loop = self.loops[loopid]
        self.clock.add((loop, ()))

class Jukebox:
    """
        administrate all songs
        
        Highest Layer!
    """
    def __init__ (self):
        self.songs = []
        self.midi = midi.MidiHandler()
        self.midi.initall()
        self.loadedsongs = []
        self.songid = -1

    def auto_song_select(self):
        def comp_list(list1, list2):
            return list(set(list1).intersection(set(list2)))

        self.midi.update()

        for song in self.songs:
            _log.info("Loading song <%s>", song.meta["name"])
            song.__init__(song.songdic, self.midi)

        mididevs = []
        for mididevnr in self.midi.devs:
            _log.info("Midi device %s", self.midi.devs[mididevnr])
            midiname = self.midi.get_name(mididevnr)
            if midiname:
                mididevs.append(midiname)

        result = {"songid":-1, "len":-1}
        for song in self.songs:
            sims_complist = len(comp_list(song.allmidinames, mididevs))
            if sims_complist > result["len"]:
                result["songid"] = self.songs.index(song)
                result["len"] = sims_complist

        return result["songid"]

    def count(self):
        return self.songs[self.songid].clock.get_count()

    def scan_dir(self, path):
        """
            Scan PATH for Songs.json
        """
        for filename in glob(join(path, "*.json")):
            _log.debug("Found file <%s>", filename)
            self.add_song(filename)

    def set_songid(self, songid):
        """
            Setzt die aktuelle SongID
        """
        if songid <= len(self.songs):
            _log.info("New SongID: %s", songid)
            self.songs[self.songid].stop_clock()
            self.songid = songid
            self.songs[self.songid].start_clock()
        else:
            _log.warning("SongID not in list!")

    def add_song (self, songdata):
        if type(songdata) == dict:
            _log.debug("Recognized dict")
            self.songs.append(Song(songdata, self.midi))
        else:
            # geht davon aus, dass es eine JSON DateiPfad ist
            _log.debug("Recognized JSON-file")
            if songdata in self.loadedsongs:
                _log.info("Song has already been added")
            else:
                self.songs.append(Song(json.load(file(songdata, "r")), self.midi))
                self.loadedsongs.append(songdata)
                self.songid = self.loadedsongs.index(songdata)

    def get_loops(self):
        return self.songs[self.songid].loops

    def get_drums(self):
        return self.songs[self.songid].drums

    def drum(self, drumid):
        self.songs[self.songid].checkdrum(drumid)

    def loop(self, loopid):
        self.songs[self.songid].checkloop(loopid)

    def debug_play (self, index):
        self.songs[index].debug_play()

if __name__ == "__main__":
    Debug_jukebox = Jukebox()
    #dg_jukebox.add_song(song)
    #Debug_jukebox.add_song("test.json")
    #dg_jukebox.debug_play(0) # Debug Funktion
    #Debug_jukebox.drum(1)
    raw_input()
